from model import common

import torch.nn as nn

url = {
    'r16f64x2': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_baseline_x2-1bc95232.pt',
    'r16f64x3': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_baseline_x3-abf2a44e.pt',
    'r16f64x4': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_baseline_x4-6b446fab.pt',
    'r32f256x2': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_x2-0edfb8a3.pt',
    'r32f256x3': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_x3-ea3ef2c6.pt',
    'r32f256x4': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_x4-4f62e9ef.pt'
}

def make_model(args, parent=False):
    return EDSR(args)

class EDSR(nn.Module):
    def __init__(self, args, conv=common.default_conv):
        super(EDSR, self).__init__()

        self.sub_mean = common.MeanShift(args.rgb_range)
        self.add_mean = common.MeanShift(args.rgb_range, sign=1)

        self.conv1 = nn.Conv2d(args.n_colors, 16, kernel_size=3, stride = 1, padding=(1,1), bias=True)
        self.conv2 = nn.Conv2d(16, 16, kernel_size=3, stride = 1, padding=(1,1), bias=True)
        self.conv3 = nn.Conv2d(16, 16, kernel_size=3, stride = 1, padding=(1,1), bias=True)
        self.conv4 = nn.Conv2d(16, 16, kernel_size=3, stride = 1, padding=(1,1), bias=True)

        
        self.activation = nn.ReLU()
        self.deconv = nn.ConvTranspose2d(16, args.n_colors, kernel_size=4, padding=(1,1), stride=2, bias=False)
        

    def forward(self, x):
        #x = self.sub_mean(x)
        layer1 = self.activation(self.conv1(x))
        layer2 = self.activation(self.conv2(layer1))
        layer3 = self.activation(self.conv3(layer2))
        layer4 = self.activation(self.conv4(layer3))
        output = self.deconv(layer4)
        #output = self.add_mean(output)
        return output 

    def load_state_dict(self, state_dict, strict=True):
        own_state = self.state_dict()
        for name, param in state_dict.items():
            if name in own_state:
                if isinstance(param, nn.Parameter):
                    param = param.data
                try:
                    own_state[name].copy_(param)
                except Exception:
                    if name.find('tail') == -1:
                        raise RuntimeError('While copying the parameter named {}, '
                                           'whose dimensions in the model are {} and '
                                           'whose dimensions in the checkpoint are {}.'
                                           .format(name, own_state[name].size(), param.size()))
            elif strict:
                if name.find('tail') == -1:
                    raise KeyError('unexpected key "{}" in state_dict'
                                   .format(name))

